﻿using UnityEngine;
using System.Collections;

//录音
public class RecordSound
{
	string[] mMicDevicesArray = null;

	public AudioSource mAudioSource;
	public RecordSound(GameObject obj)
	{
		mAudioSource = obj.GetComponent<AudioSource>();
		mMicDevicesArray = Microphone.devices;
		if (mMicDevicesArray.Length == 0)
		{
			Debug.LogError("Microphone.devices is null");
		}
		foreach (string deviceStr in mMicDevicesArray)
		{
			Debug.Log("device name = " + deviceStr);
		}
	}
	public void StartRecord()
	{
		if (!mAudioSource)
			return;
		mAudioSource.Stop();
		if (mMicDevicesArray.Length == 0)
		{
			Debug.Log("No Record Device!");
			return;
		}
		mAudioSource.clip = Microphone.Start("Built-in Microphone", true, 2, 44100);
		while (!(Microphone.GetPosition(null) > 0))
		{
		}
		mAudioSource.Play();
	}
	private float Sum(params float[] samples)
	{
		float result = 0.0f;
		for (int i = 0; i < samples.Length; i++)
		{
			float qiangdu = Mathf.Abs(samples[i]);
			if (qiangdu > result)
			{
				result = qiangdu;
			}
			// result += Mathf.Abs(samples[i]);
		}
		return result;
	}
	public float GetVolume()
	{
		if (Microphone.IsRecording(null))
		{
			int curpos = Microphone.GetPosition(null);
			// 采样数
			int sampleSize = 256;
			float[] samples = new float[sampleSize];
			int startPosition = Microphone.GetPosition(null) - (sampleSize + 1);
			if (startPosition < 0)
			{
				startPosition = 0;
			}
			// 得到数据
			mAudioSource.clip.GetData(samples, startPosition);
			return Sum(samples);// / sampleSize;
		}
		return 0;
	}
}

[RequireComponent(typeof(AudioSource))]
public class FlappyScript : MonoBehaviour
{
	public AudioClip FlyAudioClip, DeathAudioClip, ScoredAudioClip;
	public Sprite GetReadySprite;
	public float RotateUpSpeed = 1, RotateDownSpeed = 1;
	public GameObject IntroGUI, DeathGUI, Canvas;
	public Collider2D restartButtonGameCollider;
	public float VelocityPerJump = 3;
	public float XSpeed = 1;

	RecordSound mRecordSound = null;
	float volume = 0f;
	Rect rect = new Rect(0, 0, 100, 20);

	bool bigVoice = false;

	void Start()
	{
		mRecordSound = new RecordSound(this.gameObject);
		mRecordSound.StartRecord();
	}


	FlappyYAxisTravelState flappyYAxisTravelState;

	enum FlappyYAxisTravelState
	{
		GoingUp, GoingDown
	}

	Vector3 birdRotation = Vector3.zero;

	void OnGUI()
	{
		//GUI.Label(this.rect, volume.ToString());  
	}

	// Update is called once per frame
	void Update()
	{
		//handle back key in Windows Phone
		if (Input.GetKeyDown(KeyCode.Escape))
			Application.Quit();

		if (GameStateManager.GameState == GameState.Intro)
		{
			MoveBirdOnXAxis();
			if (WasVoiced()) //檢測是否有聲音
			{
				BoostOnYAxis();
				GameStateManager.GameState = GameState.Playing;
				IntroGUI.SetActive(false);
				Canvas.SetActive(false);
				ScoreManagerScript.Score = 0;
			}
		}

		else if (GameStateManager.GameState == GameState.Playing)
		{
			MoveBirdOnXAxis();
			if (WasVoiced())
			{
				BoostOnYAxis();
			}
		}

		else if (GameStateManager.GameState == GameState.Dead)
		{
			Vector2 contactPoint = Vector2.zero;

			if (Input.touchCount > 0)
				contactPoint = Input.touches[0].position;
			if (Input.GetMouseButtonDown(0))
				contactPoint = Input.mousePosition;

			//check if user wants to restart the game
			if (restartButtonGameCollider == Physics2D.OverlapPoint
				(Camera.main.ScreenToWorldPoint(contactPoint)))
			{
				GameStateManager.GameState = GameState.Intro;
				Application.LoadLevel(0);
			}
		}
	}


	void FixedUpdate()
	{
		//just jump up and down on intro screen
		if (GameStateManager.GameState == GameState.Intro)
		{
			if (GetComponent<Rigidbody2D>().velocity.y < -1) //when the speed drops, give a boost
				GetComponent<Rigidbody2D>().AddForce(new Vector2(0, GetComponent<Rigidbody2D>().mass * 5500 * Time.deltaTime)); //lots of play and stop 
			//and play and stop etc to find this value, feel free to modify
		}
		else if (GameStateManager.GameState == GameState.Playing || GameStateManager.GameState == GameState.Dead)
		{
			FixFlappyRotation();
		}
	}

	//檢測是否按鍵按下
	bool WasTouchedOrClicked()
	{
		if (Input.GetButtonUp("Jump") || Input.GetMouseButtonDown(0) ||
			(Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Ended))
		{
			return true;
		}
		else
			return false;
	}
	
	//檢測是否發聲
	bool WasVoiced()
	{
		this.volume = mRecordSound.GetVolume();  //获得音量
		if (this.volume > 0.5f && !bigVoice)
		{
			bigVoice = true;
			return true;
		}
		else
		{
			bigVoice = false;
			return false;
		}
	}

	void MoveBirdOnXAxis()
	{
		transform.position += new Vector3(Time.deltaTime * XSpeed, 0, 0);
	}

	void BoostOnYAxis()
	{
		GetComponent<Rigidbody2D>().velocity = new Vector2(0, VelocityPerJump);
		GetComponent<AudioSource>().PlayOneShot(FlyAudioClip);
	}



	/// <summary>
	/// when the flappy goes up, it'll rotate up to 45 degrees. when it falls, rotation will be -90 degrees min
	/// </summary>
	private void FixFlappyRotation()
	{
		if (GetComponent<Rigidbody2D>().velocity.y > 0) flappyYAxisTravelState = FlappyYAxisTravelState.GoingUp;
		else flappyYAxisTravelState = FlappyYAxisTravelState.GoingDown;

		float degreesToAdd = 0;

		switch (flappyYAxisTravelState)
		{
			case FlappyYAxisTravelState.GoingUp:
				degreesToAdd = 6 * RotateUpSpeed;
				break;
			case FlappyYAxisTravelState.GoingDown:
				degreesToAdd = -3 * RotateDownSpeed;
				break;
			default:
				break;
		}
		//solution with negative eulerAngles found here: http://answers.unity3d.com/questions/445191/negative-eular-angles.html

		//clamp the values so that -90<rotation<45 *always*
		birdRotation = new Vector3(0, 0, Mathf.Clamp(birdRotation.z + degreesToAdd, -90, 45));
		transform.eulerAngles = birdRotation;
	}

	/// <summary>
	/// check for collision with pipes
	/// </summary>
	/// <param name="col"></param>
	void OnTriggerEnter2D(Collider2D col)
	{
		if (GameStateManager.GameState == GameState.Playing)
		{
			if (col.gameObject.tag == "Pipeblank") //pipeblank is an empty gameobject with a collider between the two pipes
			{
				GetComponent<AudioSource>().PlayOneShot(ScoredAudioClip);
				ScoreManagerScript.Score++;
			}
			else if (col.gameObject.tag == "Pipe")
			{
				FlappyDies();
			}
		}
	}

	void OnCollisionEnter2D(Collision2D col)
	{
		if (GameStateManager.GameState == GameState.Playing)
		{
			if (col.gameObject.tag == "Floor")
			{
				FlappyDies();
			}
		}
	}

	void FlappyDies()
	{
		GameStateManager.GameState = GameState.Dead;
		DeathGUI.SetActive(true);
		GetComponent<AudioSource>().PlayOneShot(DeathAudioClip);
	}
}
